package fsevent

import (
	"errors"
	"sync"
	"time"

	"github.com/fiorix/go-eventsocket/eventsocket"
	log "github.com/sirupsen/logrus"
)

type FSClient struct {
	conn      *eventsocket.Connection
	EventChan chan *eventsocket.Event
	addr      string
	pass      string
	Connflag  bool
	sync.RWMutex
}

func New(addr string, pass string) *FSClient {
	client := &FSClient{
		addr:     addr,
		pass:     pass,
		Connflag: false,
	}
	return client
}

func (f *FSClient) Connect() error {
	c, err := eventsocket.Dial(f.addr, f.pass)
	if err != nil {
		log.WithField("func:", "FSClient read msg Connect").Errorf("connect error %s %v", f.addr, f.pass)
		return err
	}
	f.conn = c
	f.Connflag = true
	return nil
}

func (f *FSClient) ReadMsg() error {
	for {
		ev, err := f.conn.ReadEvent()
		if err != nil && err.Error() == "EOF" {
			log.WithField("func:", "FSClient readmsg").Errorf("reconnect read msg err %s", err.Error())
			return err
		} else if err != nil {
			log.WithField("func:", "FSClient readmsg").Errorf("read msg err %s", err.Error())
		} else {
			f.EventChan <- ev
			log.WithField("func:", "FSClient readmsg").Infof("read msg success the eventchan len is:%d", len(f.EventChan))

		}
	}
}
func (f *FSClient) OnEvent() {
	f.EventChan = make(chan *eventsocket.Event, 100)
	var err error
	for {
		if f.conn != nil {
			f.conn.Send("event plain CUSTOM conference::maintenance")
			f.conn.Send("event plain CHANNEL_ANSWER")
			f.conn.Send("event plain CHANNEL_HANGUP")
			err = f.ReadMsg()
		}
		log.WithField("func:", "FSClient OnEvent").Errorf("the socket disconnect")
		if !f.Reconnect(&err) {
			break
		}
	}
}

func (f *FSClient) Reconnect(err *error) bool {
	if (*err) == nil {
		return false
	}
	log.WithField("func:", "FSClient Connect").Errorf("fs reconnect the err is:%s", (*err).Error())
	if (*err).Error() != "EOF" {
		return false
	}
	f.Close()
	timer1 := time.NewTimer(time.Second * time.Duration(5))
	for {
		<-timer1.C
		c, err := eventsocket.Dial(f.addr, f.pass)
		if err == nil {
			timer1.Stop()
			f.Lock()
			f.conn = c
			f.Connflag = true
			f.Unlock()
			log.WithField("func:", "FSClient Reconnect").Infof("connect successful %s %v", f.addr, f.pass)
			break
		}
		timer1.Reset(time.Second * time.Duration(5))
		log.WithField("func:", "FSClient Connect").Errorf("connect error %s, %s %v", err.Error(), f.addr, f.pass)
	}
	return true
}

func (f *FSClient) SendMsgToFs(msg []string) error {
	var reerr error
	defer f.Reconnect(&reerr)
	conn := f.GetConn()
	if conn != nil {
		for _, v := range msg {
			log.WithField("func:", "SendMsgToFs").Errorf("the  msg is : %s", v)
			ev, err := conn.Send(v)
			if err != nil {
				reerr = err
				log.WithField("func:", "SendMsgToFs error").Errorf("the err msg is %v,%s", err.Error(), v)
				return reerr
			}
			log.WithField("func:", "SendMsgToFs success").Errorf("the ev is %v msg is : %s", ev, v)
		}
	} else {
		reerr = errors.New("fs not connect")
	}
	return reerr
}

func (f *FSClient) SingelSendMsgToFs(msg string) (*eventsocket.Event, error) {
	var reerr error
	defer f.Reconnect(&reerr)
	conn := f.GetConn()
	if conn != nil {
		ev, err := conn.Send(msg)
		if err != nil {
			reerr = err
			log.WithField("func:", "SingelSendMsgToFs error").Errorf("the err msg is %v,%s", err.Error(), msg)
		} else {
			log.WithField("func:", "SingelSendMsgToFs success").Errorf("the ev is %v msg is : %s", ev, msg)
		}
		return ev, err
	}
	return nil, errors.New("fs not connect")
}

func (f *FSClient) GetConn() *eventsocket.Connection {
	f.Lock()
	defer f.Unlock()
	if !f.Connflag {
		return nil
	}
	return f.conn
}
func (f *FSClient) Close() bool {
	f.Lock()
	defer f.Unlock()
	if !f.Connflag {
		return true
	}
	f.Connflag = false
	f.conn.Close()
	f.conn = nil
	return true
}
